package com.csu.util;

import com.csu.entity.*;
import com.csu.service.ChatService;
import com.csu.service.HeadPictureService;
import com.csu.service.UserService;
import com.csu.service.serviceImpl.ChatServiceImpl;
import com.csu.service.serviceImpl.UserServiceImpl;
import com.csu.vo.WebSocketChatInfoVo;
import com.google.gson.Gson;
import com.google.gson.JsonObject;
import jakarta.websocket.OnClose;
import jakarta.websocket.OnMessage;
import jakarta.websocket.OnOpen;
import jakarta.websocket.Session;
import jakarta.websocket.server.PathParam;
import jakarta.websocket.server.ServerEndpoint;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

@Slf4j
@Component
//前端请求后端webSocket访问路径
@ServerEndpoint("/chat/{userId}/{chatId}")
@Getter
public class MyWebSocket {
    private static ChatService chatService;
    private static UserService userService;
    private static HeadPictureService headPictureService;
    private Session session;
    private int userId;
    //设置用户当前聊天内的所有人
    private List<Integer> usersOfChat;
    //存当前在线的用户以及对应使用的chatId
    public static final Map<Integer,Integer> userMap = new HashMap<>();
    // 用来存在线连接用户信息
    public static final ConcurrentHashMap<Integer, Session> sessionPool = new ConcurrentHashMap<Integer, Session>();
    @Autowired
    public void setChatService(ChatService chatService) {
        MyWebSocket.chatService = chatService;
    }
    @Autowired
    public void setUserService(UserService userService) {
        MyWebSocket.userService = userService;
    }
    @Autowired
    public void setHeadPictureService(HeadPictureService headPictureService){MyWebSocket.headPictureService = headPictureService;}
    // 连接成功调用的方法
    @OnOpen
    public void onOpen(Session session, @PathParam(value = "userId") int userId,@PathParam(value = "chatId") int chatId) {
        System.out.println("创建webSocket"+userMap);
        this.userId=userId;
        this.session=session;

        Integer oldChatId = userMap.get(userId);
        //如果已经存在就先关闭老的webSocket
        if (oldChatId != null) {
            userMap.remove(userId);
            Session session1 = sessionPool.get(userId);
            try {
                session1.close();
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        }
        userMap.put(userId,chatId);
        sessionPool.put(userId, session);   // 存储用户的session
        log.info("【websocket消息】有新的连接，id为:" + userId+"...."+chatId+"user"+userMap);
    }

    // 连接关闭调用的方法
    @OnClose
    public void onClose() {
        System.out.println("关闭webSocket");
        System.out.println("userId:"+userId);
        userMap.remove(this.userId);
        sessionPool.remove(this.userId);
        log.info("【websocket消息】连接断开，总数为:" + userMap);
    }

    // 收到客户端消息后调用的方法
    //message=message+chatId+userId
    @OnMessage
    public void onMessage(String message){
        System.out.println("webSocket收到信息"+message);
        //获取数据
        Gson gson = new Gson();
        JsonObject jsonObject = gson.fromJson(message, JsonObject.class);

        int chatId = jsonObject.get("chatId").getAsInt();
        int userId = jsonObject.get("userId").getAsInt();
        String chatMessage = jsonObject.get("message").getAsString();
        int type = jsonObject.get("type").getAsInt();
        String voiceurl = jsonObject.get("voiceurl").getAsString();


        //后端保存
        log.info("【websocket消息】收到客户端消息:" + chatMessage);
        // 设置时间
        LocalDateTime currentDateTime = LocalDateTime.now();
        Timestamp chatInfoDate = Timestamp.valueOf(currentDateTime);
        //保存用户聊天信息
        ChatInfo chatInfo = new ChatInfo();
        chatInfo.setChatId(chatId);
        chatInfo.setUserId(userId);
        chatInfo.setChatDate(chatInfoDate);
        chatInfo.setInformation(chatMessage);
        chatInfo.setType(type);
        chatInfo.setVoiceurl(voiceurl);
        System.out.println(chatInfo);
        int msgCount = chatService.insertChatInfo(chatInfo);

        //前端发送
        //处理时间给前端
        String chatInfoDateTimeStamp = chatInfoDate.toString();
        String chatInfoDateToString = chatInfoDateTimeStamp.substring(0, chatInfoDateTimeStamp.lastIndexOf(":"));
        //获取用户的名字
        String username = userService.getUsernameByUserId(userId);
        //前端传输正确的数据对象转化为json.string
        WebSocketChatInfoVo webSocketChatInfoVo = new WebSocketChatInfoVo();
        webSocketChatInfoVo.setMessage(chatMessage);
        webSocketChatInfoVo.setUsername(username);
        webSocketChatInfoVo.setChatInfoDate(chatInfoDateToString);
        webSocketChatInfoVo.setChatId(chatId);
        webSocketChatInfoVo.setFlag(0);
        webSocketChatInfoVo.setType(type);
        webSocketChatInfoVo.setVoiceurl(voiceurl);
        webSocketChatInfoVo.setImgurl(headPictureService.getHeadPicturePathOfUser(userId));
        //用户在这个页面的信息转化为json字符串
        Gson gson1 = new Gson();
        String jsonString = gson1.toJson(webSocketChatInfoVo);

        //用户不在这个页面的信息转化为json字符串
        webSocketChatInfoVo.setFlag(1);
        Gson gson2 = new Gson();
        String jsonWrongString = gson2.toJson(webSocketChatInfoVo);

        //发送消息给这个聊天里面的所有用户
        List<Integer> chatUserIdList = chatService.getChats(chatId);

        for (int chatUserId : chatUserIdList){
            //给所有非自身的session发送信息
            if (chatUserId != userId){
                //满足这个用户建立了websocket连接，是在发送者的同页面内这两个条件就给它发送信息
                if (userMap.get(chatUserId) != null && userMap.get(chatUserId) == chatId){
                    sendOneMessage(chatUserId,jsonString);
                }else{
                    //未读信息加1
                    chatService.addUnreadCount(chatId,chatUserId);
                    Session session = sessionPool.get(chatUserId);
                    //如果用户有连接，则通知用户更新聊天列表
                    if (session != null && session.isOpen()) {
                        //发送密钥给前端要求它给对应的chatId未读信息加1
                        sendOneMessage(chatUserId,jsonWrongString);
                    }
                }
            }
            else{
                System.out.println("自身调用");
            }
        }
    }

    // 单点消息
    public void sendOneMessage(int userId, String message) {
        Session session = sessionPool.get(userId);
        if (session != null && session.isOpen()) {
            log.info("【websocket消息】 单点消息:" +"发送对象："+userId+ message);
            session.getAsyncRemote().sendText(message);
        }
    }
}
